home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 040 (1987-11-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 040 (1987-11-15)(Ossowski, Stefan)(DE)(PD).adf / A68k / A68kmain.c < prev    next >
C/C++ Source or Header  |  1989-01-18  |  18KB  |  579 lines

  1. /*------------------------------------------------------------------*/
  2. /*                                    */
  3. /*              MC68000 Cross Assembler                */
  4. /*                                    */
  5. /*           Copyright (c) 1985 by Brian R. Anderson            */
  6. /*                                    */
  7. /*          Main program - September 9, 1987            */
  8. /*                                    */
  9. /*   This program may be copied    for personal, non-commercial use    */
  10. /*   only, provided that the above copyright notice is included        */
  11. /*   on    all copies of the source code.    Copying    for any    other use   */
  12. /*   without the consent of the    author is prohibited.            */
  13. /*                                    */
  14. /*------------------------------------------------------------------*/
  15. /*                                    */
  16. /*        Originally published (in Modula-2) in            */
  17. /*        Dr.    Dobb's Journal, April, May, and June 1986.          */
  18. /*                                    */
  19. /*    AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs.    */
  20. /*                                    */
  21. /*------------------------------------------------------------------*/
  22.  
  23. char Version[] = "1.02 (September 9, 1987)";
  24.  
  25.  
  26. #include <stdio.h>
  27. #define    PRIMARY
  28. #include "a68kdef.h"
  29. #include "a68kglb.h"
  30.  
  31.  
  32. /********************************************************************/
  33. /*                                    */
  34. /*     NOTE: the following line, plus any additional references        */
  35. /*     to _fmode, is inserted to make this program work    under        */
  36. /*     the MS-DOS version of Lattice C.     It is not necessary        */
  37. /*     for the Amiga version, but does no harm if left in.        */
  38. /*                                    */
  39. /********************************************************************/
  40. int _fmode = 0;        /* File    mode - 0x8000 for binary */
  41.  
  42.  
  43.  
  44. /* Functions */
  45. extern int  LineParts(), GetField(), Instructions(), ObjDir();
  46. extern int  GetSize(), GetInstModeSize(), GetMultReg();
  47. extern int  ReadSymTab(), GetArgs(), GetAReg(),    OpenIncl();
  48. extern long AddrBndW(),    AddrBndL(), GetValue(),    CalcValue();
  49. #ifdef AZTEC_C
  50. extern char *lmalloc();
  51. #else
  52. extern char *malloc();
  53. #endif
  54. extern FILE *fopen();
  55.  
  56.  
  57.  
  58. main(argc,argv)    int argc; char *argv[];
  59. {
  60.     char ListFN[MAXFN],    SrecFN[MAXFN], EquateFN[MAXFN];    /* File    names */
  61.     int     MakeEqu;            /* Create an equate file */
  62.     FILE *EquFile;            /* Equate file pointer */
  63.     int     endfile;            /* End-of-file flag */
  64.     long maxheap, maxheap2;        /* Maximum heap    sizes */
  65.     int     cmderror, dummy;
  66.     long templong;
  67.     register struct SymTab *sym;
  68.     register int i, j;
  69.  
  70.     cmderror = FALSE;        /* Clear command-line error flag */
  71.     SourceFN[0]    = '\0';                 /* Don't have source name yet */
  72.     HeaderFN[0]    = EquateFN[0] =    '\0';   /* No header or equate files yet */
  73.     ListFN[0] =    SrecFN[0] = '\0';       /* Indicate default file names */
  74.     InclList[0]    = '\0';         /* Clear the include directory list */
  75.     IdntName[0]    = '\0';         /* Clear program unit name */
  76.     LnMax = 60;
  77.     XrefList = DumpSym = GotEqur = MakeEqu = FALSE;
  78.     SuppList = TRUE;        /* Default to no listing file */
  79.     maxheap  = DEFHEAP;        /* Primary heap    size default */
  80.     maxheap2 = DEFHEAP2;    /* Secondary heap size default */
  81.  
  82.     printf ("\n68000 Cross Assembler\n");
  83.     printf ("Copyright (c) 1985 by Brian R. Anderson\n\n");
  84.     printf ("AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs.\n");
  85.     printf ("Version %s\n\n", Version);
  86.  
  87.     for    (i = 1;    i < argc; i++) {    /* Analyze command line    */
  88.     if (argv[i][0] != '-') {
  89.         if (SourceFN[0] == '\0')
  90.         strcpy (SourceFN, argv[i]);    /* Source file name */
  91.         else if (SrecFN[0] == '\0')
  92.         strcpy (SrecFN,    argv[i]);    /* Object file name */
  93.         else if (ListFN[0] == '\0')
  94.         strcpy (ListFN,    argv[i]);    /* Listing file    name */
  95.         else {
  96.         printf ("Too many file names.\n");
  97.         cmderror = TRUE;
  98.         }
  99.     } else {
  100.         switch (argv[i][1])    {
  101.         case 'D':
  102.         case 'd':
  103.         DumpSym     = TRUE;
  104.         if (argv[i][2])    {
  105.             printf ("Invalid symbol table dump switch.\n");
  106.             cmderror = TRUE;
  107.         }
  108.         break;
  109.         case 'E':                           /* Equate file name */
  110.         case 'e':
  111.         MakeEqu    = TRUE;
  112.         if (EquateFN[0]) {
  113.             printf ("Equate file is declared more than once.\n");
  114.             cmderror = TRUE;
  115.         } else if (argv[i][2])
  116.             strcpy (EquateFN, &argv[i][2]);
  117.         break;
  118.         case 'H':                           /* Header file name */
  119.         case 'h':
  120.         if (HeaderFN[0]) {
  121.             printf ("Header file is declared more than once.\n");
  122.             cmderror = TRUE;
  123.         } else if (argv[i][2]) {
  124.             strcpy (HeaderFN, &argv[i][2]);
  125.         } else {
  126.             printf ("Header file name is missing\n");
  127.             cmderror = TRUE;
  128.         }
  129.         break;
  130.         case 'I':                           /* Include directories */
  131.         case 'i':
  132.         if (argv[i][2])    {
  133.             if (InclList[0])
  134.             strcat (InclList, ","); /* Add to previous list */
  135.             strcat (InclList, &argv[i][2]);
  136.         } else {
  137.             printf ("Include directory list is missing.\n");
  138.             cmderror = TRUE;
  139.         }
  140.         break;
  141.         case 'L':                           /* Listing file name */
  142.         case 'l':
  143.         SuppList = FALSE;        /* Produce a listing */
  144.         if (ListFN[0]) {
  145.             printf ("List file is declared more than once.\n");
  146.             cmderror = TRUE;
  147.         } else if (argv[i][2])
  148.             strcpy (ListFN, &argv[i][2]);
  149.         break;
  150.         case 'O':                           /* Object file name */
  151.         case 'o':
  152.         if (SrecFN[0]) {
  153.             printf ("Object file is declared more than once.\n");
  154.             cmderror = TRUE;
  155.         } else if (argv[i][2]) {
  156.             strcpy (SrecFN, &argv[i][2]);
  157.         } else {
  158.             printf ("Object file name is missing\n");
  159.             cmderror = TRUE;
  160.         }
  161.         break;
  162.         case 'P':
  163.         case 'p':
  164.         if ((LnMax = CalcValue(&argv[i][2], 0))    < 10) {
  165.             printf ("Invalid page depth.\n");
  166.             cmderror = TRUE;
  167.         }
  168.         break;
  169.         case 'S':
  170.         case 's':
  171.         SFormat     = TRUE;
  172.         if (argv[i][2])    {
  173.             printf ("Invalid S-format switch.\n");
  174.             cmderror = TRUE;
  175.         }
  176.         break;
  177.         case 'W':
  178.         case 'w':
  179.         if (argv[i][2] != ',') {
  180.             maxheap = CalcValue(&argv[i][2], 0);
  181.             if (maxheap    < MAXLINE)
  182.             maxheap    = MAXLINE;    /* Minimum heap    size */
  183.             maxheap &= ~3L;        /* Long-word alignment */
  184.         }
  185.         for (j = 2; argv[i][j];    j++) {
  186.             if (argv[i][j] == ',') {    /* Find secondary size */
  187.             maxheap2 = CalcValue(&argv[i][j+1], 0);
  188.             if (maxheap2 < MAXLINE)    {
  189.                 maxheap2 = MAXLINE;
  190.             }
  191.             maxheap2 &= ~3L;
  192.             break;
  193.             }
  194.         }
  195.         break;
  196.         case 'X':
  197.         case 'x':
  198.         XrefList  = TRUE;
  199.         SuppList = FALSE;    /* We must want    a listing */
  200.         if (argv[i][2])    {
  201.             printf ("Invalid cross-reference switch.\n");
  202.             cmderror = TRUE;
  203.         }
  204.         break;
  205.         default:
  206.         printf ("Unrecognized switch.\n");
  207.         cmderror = TRUE;
  208.         break;
  209.         }
  210.     }
  211.     }
  212.  
  213.     if (SourceFN[0] == '\0') {          /* Default list file name */
  214.     printf ("Source file name is missing.\n");
  215.     cmderror = TRUE;
  216.     }
  217.  
  218.     if (EquateFN[0] == '\0') {          /* Default equate file name */
  219.     strcpy (EquateFN, SourceFN);
  220.     i = strlen (EquateFN);
  221.     while (--i > 0)    {
  222.         if (EquateFN[i] == '.') {
  223.         EquateFN[i] = '\0';     /* Chop off name extension */
  224.         break;
  225.         }
  226.     }
  227.     strcat (EquateFN, ".equ");      /* Equate file name extension */
  228.     }
  229.  
  230.     if (ListFN[0] == '\0') {            /* Default list file name */
  231.     strcpy (ListFN,    SourceFN);
  232.     i = strlen (ListFN);
  233.     while (--i > 0)    {
  234.         if (ListFN[i] == '.') {
  235.         ListFN[i] = '\0';       /* Chop off name extension */
  236.         break;
  237.         }
  238.     }
  239.     strcat (ListFN,    ".lst");        /* List file name extension */
  240.     }
  241.  
  242.     if (SrecFN[0] == '\0') {            /* Default object file name */
  243.     strcpy (SrecFN,    SourceFN);
  244.     i = strlen (SrecFN);
  245.     while (--i > 0)    {
  246.         if (SrecFN[i] == '.') {
  247.         SrecFN[i] = '\0';       /* Chop off name extension */
  248.         break;
  249.         }
  250.     }
  251.     if (SFormat)
  252.         strcat (SrecFN, ".s");      /* S-format name extension */
  253.     else
  254.         strcat (SrecFN, ".o");      /* AmigaDOS format extension */
  255.     }
  256.  
  257.     if (strcmp (SourceFN, EquateFN) == 0) {
  258.     printf ("Source and equate file names are the same.\n");
  259.     cmderror = TRUE;
  260.     }
  261.     if (strcmp (SourceFN, ListFN) == 0)    {
  262.     printf ("Source and listing file names are the same.\n");
  263.     cmderror = TRUE;
  264.     }
  265.     if (strcmp (SourceFN, SrecFN) == 0)    {
  266.     printf ("Source and object file names are the same.\n");
  267.     cmderror = TRUE;
  268.     }
  269.     if (strcmp (EquateFN, ListFN) == 0)    {
  270.     printf ("Equate and listing file names are the same.\n");
  271.     cmderror = TRUE;
  272.     }
  273.     if (strcmp (EquateFN, SrecFN) == 0)    {
  274.     printf ("Equate and object file names are the same.\n");
  275.     cmderror = TRUE;
  276.     }
  277.     if (strcmp (ListFN,    SrecFN)    == 0) {
  278.     printf ("Listing and object file names are the same.\n");
  279.     cmderror = TRUE;
  280.     }
  281.  
  282. /*    Open Files.    */
  283.  
  284.     _fmode = 0x8000;            /******    MS-DOS only ******/
  285.     if (!cmderror) {
  286.     if ((InFile = fopen (SourceFN, "r")) == NULL) {
  287.         printf ("Unable to open source file.\n");
  288.         cmderror = TRUE;
  289.     }
  290.     }
  291.     _fmode = 0;                /******    MS-DOS only ******/
  292.     if (!cmderror && MakeEqu) {
  293.     if ((EquFile = fopen (EquateFN,    "w")) == NULL) {
  294.         printf ("Unable to open equate file.\n");
  295.         cmderror = TRUE;
  296.         fclose (InFile);        /* Close any opened files */
  297.     }
  298.     }
  299.     if (!cmderror && !SuppList)    {
  300.     if ((List = fopen (ListFN, "w")) == NULL) {
  301.         printf ("Unable to open listing file.\n");
  302.         cmderror = TRUE;
  303.         fclose (InFile);
  304.         if (MakeEqu)
  305.         fclose (EquFile);
  306.     }
  307.     }
  308.     if (!SFormat) _fmode = 0x8000;    /******    MS-DOS only ******/
  309.     if (!cmderror) {
  310.     if ((Srec = fopen (SrecFN, "w")) == NULL ) {
  311.         printf ("Unable to open object code file.\n");
  312.         cmderror = TRUE;
  313.         fclose (InFile);
  314.         if (MakeEqu)
  315.         fclose (EquFile);
  316.         if (!SuppList)
  317.         fclose (List);
  318.     }
  319.     }
  320.  
  321.     if (cmderror) {
  322.     printf ("\n");
  323.     printf ("Usage: a68k <source file>\n");
  324.     printf ("            [-e<equate file>]\n");
  325.     printf ("            [-h<header file>]\n");
  326.     printf ("            [-i<include dirlist>]\n");
  327.     printf ("            [-l<listing file>]\n");
  328.     printf ("            [-o<object file>]\n");
  329.     printf ("            [-p<page depth>]\n");
  330.     printf ("            [-w[<heap size>][,<heap size>]]\n");
  331.     printf ("            [-d] [-s] [-x]\n\n");
  332.     printf ("Command-line arguments can appear in any order.\n");
  333.     printf ("Heap size default (bytes):  -w");
  334.     printf ("%ld,%ld\n", (long) DEFHEAP, (long) DEFHEAP2);
  335.     printf ("\n");
  336.     exit(20);
  337.     }
  338.  
  339. #ifdef AZTEC_C
  340.     Heap = lmalloc (maxheap);
  341. #else
  342.     Heap = malloc ((unsigned) maxheap);
  343. #endif
  344.     if (Heap ==    NULL) {
  345.     printf ("Unable to allocate primary heap!\n");
  346.     exit(20);
  347.     }
  348.     HeapLim = Heap;        /* Heap    limit (start out empty)    */
  349.     LowHeap = (Heap + maxheap);
  350.     SymStart = (struct SymTab *) (LowHeap);    /* Symbol table    */
  351.  
  352. #ifdef AZTEC_C
  353.     Heap2 = lmalloc (maxheap2);
  354. #else
  355.     Heap2 = malloc ((unsigned) maxheap2);
  356. #endif
  357.     if (Heap2 == NULL) {
  358.     printf ("Unable to allocate secondary heap!\n");
  359.     exit(20);
  360.     }
  361.     NextFNS = Heap2;
  362.     InF    = (struct InFCtl *) (Heap2 + maxheap2);
  363.     LowInF = --InF;
  364.     InFNum = OuterMac =    SkipNest = InF->Pos = InF->MCnt    = 0;
  365.     InF->Line =    0;
  366.     InF->UPtr =    0;
  367.     InF->NPtr =    NextFNS;
  368.     InF->NArg =    -1;
  369.     strcpy (NextFNS, SourceFN);
  370.     NextFNS += strlen (SourceFN) + 1;
  371.     High2 = NextFNS;
  372.     Low2  = (char *) LowInF;
  373.  
  374.     _fmode = 0x8000;            /******    MS-DOS only ******/
  375.     printf ("\nAssembling %s\n\n\n", SourceFN);
  376.  
  377. /*-------------------------------------------------------------------
  378.  
  379.     Begin Pass 1.
  380.                                    */
  381.     printf ("PASS 1\n");
  382.     LineCount =    LabLine    = MacCount = ErrorCount    = NumSyms = 0;
  383.     AddrCnt = SectStart    = 0L;    /* Assume ORG =    0 to start */
  384.     CurrHunk = NextHunk    = 0L;    /* Start in hunk zero */
  385.     HunkType = HunkNone;    /* We're not in a hunk yet */
  386.     HunkFlags =    SectLine = 0;
  387.     endfile = ListOff =    Pass2 =    FALSE;
  388.  
  389.     while (!endfile && (strcmp (OpCode,    "END") != 0)) {
  390.     PrevDir    = Dir;            /* Save    previous directive */
  391.     endfile    = LineParts (dummy);    /* Get a statement */
  392.     Dir = ObjDir (Srec);        /* Process directives */
  393.     GetObjectCode (dummy);        /* Length if executable    */
  394.  
  395.     if ((HunkType == HunkNone) && (AddrAdv != 0)) {
  396.         Sym    = SymStart;    /* Insert at head of table */
  397.         templong = (long) HunkCode << 16;
  398.         AddSymTab ("  ", 0L, templong, LineCount, 16);
  399.         Sect = Sym;        /* Create an unnamed section */
  400.         HunkType = HunkCode;
  401.         SectLine = LineCount;
  402.         NextHunk++;
  403.     }
  404.     if ((Label[0] != '\0')
  405.     && (Dir    != Set)    && (Dir    != Equr) && (Dir != Reg)) {
  406.         if (!ReadSymTab (Label)) {        /* Make    a new entry */
  407.         AddSymTab (Label, AddrCnt, CurrHunk, LineCount,    0);
  408.         } else if ((Sym->Flags & 1)        /* If dup., ignore */
  409.         || (Sym->Defn == 0)) {        /* else    fill in    */
  410.         Sym->Val = AddrCnt;        /* Current loc.    */
  411.         Sym->Hunk = CurrHunk;        /* Hunk    number */
  412.         Sym->Defn = LineCount;        /* Statement number */
  413.         Sym->Flags &= ~1;        /* Clear XREF flag */
  414.         }
  415.         if (Dir == Equ) {
  416.         Sym->Val = ObjSrc;        /* Equated value */
  417.         Sym->Hunk = Src.Hunk;        /* Hunk    number */
  418.         }
  419.     }
  420.     AddrCnt    += AddrAdv;    /* Advance location counter */
  421.     }
  422.  
  423.  
  424. /*----------------------------------------------------------------
  425.  
  426.     Begin Pass 2.
  427.                                    */
  428.     printf ("PASS 2\n");
  429.     InF    = (struct InFCtl *) (Heap2 + maxheap2);
  430.     InF--;
  431.     InFNum = OuterMac =    SkipNest = InF->Pos = InF->MCnt    = 0;
  432.     InF->Line =    0;
  433.     InF->UPtr =    0;
  434.     InF->NPtr =    Heap2;
  435.     InF->NArg =    -1;
  436.     fclose (InFile);            /* "Rewind" the source file */
  437.     InFile = fopen (SourceFN, "r");
  438.     NextFNS = Heap2 + strlen (SourceFN)    + 1;
  439.     Pass2 = TRUE;
  440.     LineCount =    LabLine    = MacCount = ErrorCount    = 0;
  441.     AddrCnt = CurrHunk = SectStart = EndAddr = 0L;
  442.     HunkType = HunkNone;
  443.     HunkFlags =    SectLine = 0;
  444.     endfile = ListOff =    FALSE;
  445.     if ((Sym = SymStart) < (struct SymTab *) (Heap + maxheap)) {
  446.     while (Sym->Flags & 16)    {
  447.         Sym->Val = 0L;    /* Back    to start of all    sections */
  448.         Sym++;
  449.     }
  450.     }
  451.     TTLstring[0] = '\0';        /* Clear title string */
  452.     if ((templong = (HeapLim - Heap) & 3L) != 0)
  453.     HeapLim    += 4 - templong;
  454.     HighHeap = HeapLim;        /* High-water mark in heap */
  455.     RelStart = (struct RelTab *) HeapLim;    /* Relocation table */
  456.     RefStart = (struct Ref *) SymStart;    /* Cross-reference table */
  457.  
  458. /* Sign    on messages for    listing    file */
  459.     LnCnt = 999;
  460.     PgCnt = 0;
  461.     TTLstring[0] = '\0';
  462.     if (!SuppList) {
  463.     CheckPage (List, FALSE);            /* Print headings */
  464.     fprintf    (List, "68000 Cross Assembler\n");
  465.     fprintf    (List, "Copyright (c) 1985 by Brian R. Anderson\n\n");
  466.     fprintf    (List, "AmigaDOS conversion copyright (c) 1987");
  467.     fprintf    (List, " by Charlie Gibbs.\n");
  468.     fprintf    (List, "Version %s\n\n", Version);
  469.     LnCnt += 6;
  470.     }
  471.  
  472.     StartSrec (Srec, IdntName);        /* Write object    header record */
  473.  
  474. /*    Process    the second pass.    */
  475.  
  476.     OpCode[0] =    '\0';                   /* Kill "END" from pass 1! */
  477.     while (!endfile && (strcmp(OpCode,"END") != 0)) {
  478.     PrevDir    = Dir;            /* Save    previous directive */
  479.     endfile    = LineParts (dummy);    /* Get a statement */
  480.     if (!endfile) {
  481.         Dir    = ObjDir (Srec);    /* Process directives */
  482.         GetObjectCode (dummy);    /* Executable object code */
  483.         if (Label[0] != '\0') {     /* If statement is labeled, */
  484.         ReadSymTab (Label);    /*  check for duplicate    defn. */
  485.         if (Sym->Defn != LineCount) {
  486.             AddRef (LineCount);    /* Got one - flag as reference */
  487.             if (Dir == Set) {
  488.             if ((Sym->Flags    & 4) ==    0)
  489.                 Error (0, SymDup);    /* Can't SET normal label */
  490.             } else {
  491.             Error (0, SymDup);    /* Ordinary duplicate */
  492.             }
  493.         } else if (Dir == Set) {
  494.             AddRef (LineCount);    /* Flag    all SETs as references */
  495.         } else {
  496.             if (Sym->Val != AddrCnt)
  497.             if ((Dir != Equ) && (Dir != Equr) && (Dir != Reg))
  498.                 Error (0, Phase);    /* Assembler error */
  499.         }
  500.         }
  501.         if (!SuppList)
  502.         WriteListLine (List);
  503.         WriteSrecLine (Srec);
  504.         AddrCnt += AddrAdv;        /* Advance locaton counter */
  505.     } else {
  506.         Error (0, EndErr);        /* END statement is missing */
  507.         if (!SuppList)
  508.         WriteListLine (List);
  509.     }
  510.     }
  511.  
  512. /*---------------------------------------------------------------------
  513.  
  514.     Clean up.
  515.                                 */
  516.  
  517.     fclose (InFile);        /* Finished with source    file */
  518.  
  519.     EndSdata (Srec, EndAddr);    /* Write remaining data    and end    record */
  520.     fclose (Srec);        /* Finished with object    file */
  521.  
  522.     if (XrefList)
  523.     WriteSymTab (List);    /* List    the symbol table */
  524.  
  525. /* Write all absolute symbols to an equate file    if desired. */
  526.     if (MakeEqu) {
  527.     fprintf    (EquFile, "* Equate file for %s\n", SourceFN);
  528.     fprintf    (EquFile, "* Created by A68k version %s\n", Version);
  529.     for (i = 0, sym    = SymStart; i <    NumSyms; i++, sym++) {
  530.         if (((sym->Hunk & 0x00007FFFL) == ABSHUNK)
  531.         && ((sym->Flags == 0) || (sym->Flags == 2))) {
  532.         fprintf    (EquFile, "%s\tEQU\t$", sym->Nam);
  533.         LongPut    (EquFile, sym->Val, 4);
  534.         fprintf    (EquFile, "\n");
  535.         }
  536.     }
  537.     fclose (EquFile);
  538.     }
  539.  
  540. /* Write error count to    console    and listing file. */
  541.     printf ("    \n\nEnd of assembly - ");
  542.     if (!SuppList)
  543.     fprintf    (List, "\n\nEnd of assembly - ");
  544.     if (ErrorCount == 0) {
  545.     printf ("no errors were found.\n\n");
  546.     if (!SuppList)
  547.         fprintf (List, "no errors were found.\n\n");
  548.     } else if (ErrorCount == 1)    {
  549.     printf ("1 error was found.\n\n");
  550.     if (!SuppList)
  551.         fprintf (List, "1 error was found.\n\n");
  552.     } else {
  553.     printf ("%d errors were found.\n\n", ErrorCount);
  554.     if (!SuppList)
  555.         fprintf (List, "%d errors were found.\n\n", ErrorCount);
  556.     }
  557.     templong = (long) (HighHeap    - Heap);
  558.     if (LowHeap    < (char    *) RefStart)
  559.     templong += (long) (Heap + maxheap - LowHeap);
  560.     else
  561.     templong += (long) (Heap + maxheap - (char *) RefStart);
  562.     printf ("Heap usage (bytes):  -w%ld", templong);
  563.     if (!SuppList)
  564.     fprintf    (List, "Heap usage (bytes):  -w%ld", templong);
  565.     templong = (long) (High2 - Heap2);
  566.     if (Low2 < (char *)    LowInF)
  567.     templong += (long) (Heap2 + maxheap2 - Low2);
  568.     else
  569.     templong += (long) (Heap2 + maxheap2 - (char *)    LowInF);
  570.     printf (",%ld\n\n", templong);
  571.     if (!SuppList) {
  572.     fprintf    (List, ",%ld\n\f", templong);   /* One last page eject */
  573.     fclose (List);        /* Finished with listing file */
  574.     }
  575.     free (Heap);        /* Release heap    space */
  576.     free (Heap2);
  577.     exit (ErrorCount ? 10 : 0);    /* All done */
  578. }
  579.